﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DomainDriver.CommonUtilities.Enums;
using DomainDriver.CommonUtilities.Reflectors;
using DomainDriver.DomainModeling.Attributes;
using DomainDriver.DomainModeling.DomainModels;
using DomainDriver.DomainModeling.DomainObjects;
using DomainDriver.DomainModeling.Repositories;

namespace DomainDriver.DomainModeling.DomainObjects
{
    public class EnumDomainObject<ENUM, KEYED_DOMAIN_OBJECT> : KeyedDomainObjectBase<ENUM, KEYED_DOMAIN_OBJECT>
        where KEYED_DOMAIN_OBJECT : EnumDomainObject<ENUM, KEYED_DOMAIN_OBJECT>, new()
        where ENUM : struct, IComparable, IFormattable, IConvertible
    {
        #region Static Members

        public static void LoadEnumerationsValues(IDomainModel domainModel)
        {
            IRepository<ENUM, KEYED_DOMAIN_OBJECT> repository = domainModel.GetRepository<ENUM, KEYED_DOMAIN_OBJECT>();
            Type enumType = typeof(ENUM);

            foreach (ENUM key in Enum.GetValues(enumType))
            {
                if (repository.Exists(key))
                { continue; }

                KEYED_DOMAIN_OBJECT domainObject = new KEYED_DOMAIN_OBJECT();
                domainObject.m_Key = key;
                repository.Add(domainObject);
            }
        }

        #endregion

        #region EnumDomainObject Implementation

        public EnumDomainObject(ENUM enumValue)
        {
            EnumUtilities.AssertTypeIsAnEnum<ENUM>();
            m_Key = enumValue;
        }

        public EnumDomainObject(int key)
            : this(EnumUtilities.ConvertIntToEnum<ENUM>(key))
        {
            // do nothing
        }

        public EnumDomainObject()
            : this(default(ENUM))
        {
            // do nothing
        }

        [Unique]
        [NotNull]
        [NotEqualToValue("")]
        public string Name
        {
            get
            {
                string name = EnumUtilities.GetNameOfValue<ENUM>(m_Key);
                return name;
            }
        }

        public Type EnumType
        {
            get
            {
                return typeof(ENUM);
            }
        }

        #endregion

        #region DomainObjectBase Implementation

        public override KEYED_DOMAIN_OBJECT Copy()
        {
            KEYED_DOMAIN_OBJECT newObject = new KEYED_DOMAIN_OBJECT();
            CopyTo(newObject);
            return newObject;
        }

        public override void CopyTo(KEYED_DOMAIN_OBJECT otherObject)
        {
            otherObject.m_Key = m_Key;
        }

        public override bool Equals(KEYED_DOMAIN_OBJECT otherObject)
        {
            if (!m_Key.Equals(otherObject.m_Key))
            {
                return false;
            }
            if (!Name.Equals(otherObject.Name))
            {
                return false;
            }
            return true;
        }

        #endregion
    }
}